﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using System.Windows.Forms;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using LIK.NetworkTools;
using LIK.WakeOnLan.Code;
using LIK.WakeOnLan.Controls;
using LIK.WakeOnLan.Network;
using LIK.WakeOnLan.Properties;

namespace LIK.WakeOnLan.Forms
{
    public partial class FormMain : XtraForm
    {
        private Dictionary<string, NetworkClient> netFavClients;

        private NetworkClient SelectedNetworkClient
        {
            set
            {
                this.dxErrorProvider.ClearErrors();
                popupContainerEditClients.Tag = value;
                if (value != null)
                {
                    popupContainerEditClients.Text = value.ToString();
                    popupContainerEditClients.ToolTip = value.GetFullInfo();
                }
                else
                {
                    popupContainerEditClients.Text = string.Empty;
                    popupContainerEditClients.ToolTip = string.Empty;
                }
            }
            get
            {
                if (popupContainerEditClients.Tag == null)
                {
                    return null;
                }
                return (NetworkClient)popupContainerEditClients.Tag;
            }
        }

        public FormMain()
        {
            InitializeComponent();
        }

        private void simpleButtonClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.LoadDefaultNetworkInterface();

            this.LoadQuickNetworkClientsList();

            this.ReloadNetworkScanList();

            this.VerifyNicInterfaces();

            this.WindowState = FormWindowState.Minimized;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            if (this.SelectedNetworkClient != null)
            {
                Settings.Default.SelectedClientMac = this.SelectedNetworkClient.MacAddress;
            }
            if (NicEnumerator.Instance.SelectedNic != null)
            {
                Settings.Default.SelectedNicMac = NicEnumerator.Instance.SelectedNic.MacAddress;
            }
            Settings.Default.Save();
            ApplicationConfigSaver.SaveNetworkClients(NetworkClients.Instance);
            ApplicationConfigSaver.SaveQuickList(this.netFavClients);
        }

        private void LoadDefaultNetworkInterface()
        {
            NicEnumerator.SetDefaultNic(Settings.Default.SelectedNicMac);

            var localIp = NicEnumerator.Instance.SelectedNic != null
                ? NicEnumerator.Instance.SelectedNic.Ip
                : "0.0.0.0";
            this.Text = String.Format("WOL [{0}]", localIp);
            if (NicEnumerator.Instance.SelectedNic == null)
            {
                XtraMessageBox.Show("Active network interface is not found\n\nSelect default NIC to continue");
            }
        }

        private void LoadQuickNetworkClientsList()
        {
            this.netFavClients = ApplicationConfigSaver.LoadQuickList();
            //var nClient = new NetworkClient("NAS", "192.168.88.44", "2c:b0:5d:be:80:ca".ToUpper());
            //this.SelectedNetworkClient = nClient;
            //this.netFavClients.Add(nClient.Guid, nClient);

            if (!string.IsNullOrEmpty(Settings.Default.SelectedClientMac))
            {
                this.SelectedNetworkClient =
                    this.netFavClients.FirstOrDefault(
                        n => n.Value.MacAddress.Equals(Settings.Default.SelectedClientMac)).Value;
            }
            if (this.SelectedNetworkClient == null && netFavClients.Count > 0)
            {
                this.SelectedNetworkClient = this.netFavClients.First().Value;
            }
        }

        private void VerifyNicInterfaces()
        {
            if (NicEnumerator.Instance.SelectedNic == null)
            {
                btnScanNetwork.Enabled = false;
                popupContainerEditClients.Enabled = false;
                popupContainerEditClients.Properties.Buttons[1].Enabled = false;
            }
            else
            {
                btnScanNetwork.Enabled = true;
                popupContainerEditClients.Enabled = true;
                popupContainerEditClients.Properties.Buttons[1].Enabled = true;
            }
        }

        private void ReloadNetworkScanList()
        {
            this.popupContainerControlClients.Controls.Clear();
            this.popupContainerControlClients.Height = this.netFavClients.Count * 20;
            foreach (var kvp in this.netFavClients)
            {
                popupContainerControlClients.Controls.Add(this.GetEditor(kvp.Value));
            }
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            using (var frmAbout = new FormAbout())
            {
                frmAbout.ShowDialog(this);
            }
        }

        private ClientEditControl GetEditor(NetworkClient nClient)
        {
            var editControl = new ClientEditControl
            {
                NetworkClient = nClient,
                EditAction = EditNetworkClient,
                DeleteAction = DeleteNetworkClient,
                SelectAction = SelectNetworkClient,
                Dock = DockStyle.Top
            };
            return editControl;
        }

        private void SelectNetworkClient(string macaddress)
        {
            this.dxErrorProvider.ClearErrors();
            this.popupContainerEditClients.ClosePopup();
            this.SelectedNetworkClient = netFavClients[macaddress];
        }

        private void DeleteNetworkClient(string macAddress)
        {
            this.popupContainerEditClients.ClosePopup();
            if (XtraMessageBox.Show(this, "Delete Network Cllient Info?", "?", MessageBoxButtons.YesNo) != DialogResult.Yes)
            {
                return;
            }
            if (this.SelectedNetworkClient != null &&  this.SelectedNetworkClient.MacAddress.Equals(macAddress))
            {
                this.SelectedNetworkClient = null;
            }
            netFavClients.Remove(macAddress);
            foreach (Control editor in popupContainerControlClients.Controls)
            {
                if (((ClientEditControl)editor).NetworkClient.MacAddress.Equals(macAddress))
                {
                    popupContainerControlClients.Controls.Remove( editor);
                    break;
                }
            }
            popupContainerControlClients.Height = this.netFavClients.Count * 20;
        }

        private void EditNetworkClient(NetworkClient nClient)
        {
            this.popupContainerEditClients.ClosePopup();
            using (var fnc = new FormNetworkClient())
            {
                fnc.InEditMode();
                fnc.NetworkClient = nClient;
                if (fnc.ShowDialog(this) == DialogResult.OK)
                {
                    netFavClients[nClient.MacAddress] = (fnc.NetworkClient);
                    foreach (Control editor in popupContainerControlClients.Controls)
                    {
                        var updatedNClient = ((ClientEditControl) editor).NetworkClient;
                        if (updatedNClient.MacAddress.Equals(nClient.MacAddress))
                        {
                            ((ClientEditControl)editor).NetworkClient = netFavClients[nClient.MacAddress];
                            break;
                        }
                    }
                    if (this.SelectedNetworkClient.MacAddress.Equals(nClient.MacAddress))
                    {
                        this.SelectedNetworkClient = netFavClients[nClient.MacAddress];
                    }
                }
            }
        }

        private void popupContainerEditClients_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            if (e.Button.Index == 1)
            {
                this.dxErrorProvider.ClearErrors();
                this.ValidateChildren(ValidationConstraints.Enabled);
                if (this.dxErrorProvider.HasErrors)
                {
                    return;
                }
                this.WakeUpNetworkClient(this.SelectedNetworkClient);
            }
            if (e.Button.Index == 0)
            {
                this.ShowClientEditorDialog();
            }
        }

        private void popupContainerEditClients_Validating(object sender, CancelEventArgs e)
        {
            if (popupContainerEditClients.Tag == null)
            {
                this.dxErrorProvider.SetError(popupContainerEditClients, "Add or select Network Client");
            }
        }

        private void btnScanNetwork_Click(object sender, EventArgs e)
        {
            using (var frmNetworkDevices = new FormNetworkScanner())
            {
                frmNetworkDevices.AsScanerOnly();
                if (frmNetworkDevices.ShowDialog(this) == DialogResult.OK)
                {
                    this.ShowClientEditorDialog(frmNetworkDevices.NetworkClient);
                }
            }
        }


        private void ShowClientEditorDialog(NetworkClient inputNClient = null)
        {
            using (var fnc = new FormNetworkClient())
            {
                if (inputNClient != null)
                {
                    fnc.NetworkClient = inputNClient;
                }
                if (fnc.ShowDialog(this) == DialogResult.OK)
                {
                    var nClient = fnc.NetworkClient;
                    if (netFavClients.ContainsKey(nClient.MacAddress))
                    {
                        XtraMessageBox.Show("The same MAC addess already present", "Favourits");
                        return;
                    }
                    netFavClients.Add(nClient.MacAddress, nClient);
                    popupContainerControlClients.Controls.Add(GetEditor(nClient));
                    popupContainerControlClients.Height = this.netFavClients.Count * 20;
                    this.SelectedNetworkClient = fnc.NetworkClient;
                }
            }
        }

        private void hyperLinkEditAbout_OpenLink(object sender, OpenLinkEventArgs e)
        {

        }

        private void btnSettings_Click(object sender, EventArgs e)
        {
            using (var frmSettings = new FormSettings())
            {
                frmSettings.ShowDialog(this);
                this.VerifyNicInterfaces();
                this.LoadDefaultNetworkInterface();
            }
        }

        #region Notify Icon

        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        private void tsmnuExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (XtraMessageBox.Show("Would you like to exit?", "Wake Up On Lan", MessageBoxButtons.YesNo) ==
                DialogResult.Yes)
            {
                return;
            }
            this.WindowState = FormWindowState.Minimized;
            e.Cancel = true;
        }

        private void FormMain_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == this.WindowState)
            {
                this.PopulateNotifyIconContextMenu();
                notifyIcon.Visible = true;
                notifyIcon.ShowBalloonTip(500);
                this.Hide();
            }
            else if (FormWindowState.Normal == this.WindowState)
            {
                notifyIcon.Visible = false;
            }
        }

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void tsmnuOpenGui_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void tsmnuScanner_Click(object sender, EventArgs e)
        {
            notifyIcon_MouseDoubleClick(null, null);
            btnScanNetwork_Click(null, null);
        }

        private void PopulateNotifyIconContextMenu()
        {
            foreach (ToolStripMenuItem dropDownItem in  tsmnuWakeUpNetClients.DropDownItems)
            {
                dropDownItem.Click -= mnuWakeUpClient_Click;
            }
            tsmnuWakeUpNetClients.DropDownItems.Clear();
            foreach (var kvp in this.netFavClients)
            {
                ToolStripMenuItem mnu = new ToolStripMenuItem(kvp.Value.ToString()) {Tag = kvp.Value};
                if (kvp.Value.Status == NetworkClientStatus.On)
                    mnu.Image = Resources.bullet_green;
                else if (kvp.Value.Status == NetworkClientStatus.Down)
                    mnu.Image = Resources.bullet_red;
                else
                    mnu.Image = Resources.bullet_yellow;
                mnu.Click += mnuWakeUpClient_Click;
                tsmnuWakeUpNetClients.DropDownItems.Add(mnu);
            }
            tsmnuWakeUpNetClients.Enabled = netFavClients.Count > 0;
        }

        private void mnuWakeUpClient_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem mnu = (ToolStripMenuItem)sender;
            var nClient = mnu.Tag as NetworkClient;
            this.WakeUpNetworkClient(nClient);
        }

        #endregion

        private void WakeUpNetworkClient(NetworkClient networkClient)
        {
            var networkPresent = NetworkInterface.GetIsNetworkAvailable();
            if (!networkPresent)
            {
                XtraMessageBox.Show("Network is not available");
                return;
            }
            if (networkClient == null)
            {
                return;
            }
            if (networkClient.IsOnline())
            {
                XtraMessageBox.Show("Network client is online");
                return;
            }
            popupContainerEditClients.Properties.Buttons[1].Enabled = false;
            this.pictureEdit.Visible = true;
            Application.DoEvents();
            var t = new Thread(SendWolCommandThread);
            t.Start();
            while (t.IsAlive)
            {
                Application.DoEvents();
            }
            this.pictureEdit.Visible = false;
            popupContainerEditClients.Properties.Buttons[1].Enabled = true;
        }

        private void SendWolCommandThread()
        {
            var nClient = this.SelectedNetworkClient;
            Application.DoEvents();
            WolCommand.SendWakUpOnLanMessage(nClient);
            Thread.Sleep(250);
        }

        private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {

            }
        }








    }
}
